/**
 This program is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation, either version 3 of the License, or
 (at your option) any later version.

 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.

 You should have received a copy of the GNU General Public License
 along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
#include "WProgram.h"
#include "Sprite.h"
#include "Matrix.h"

#ifndef MatrixFX_h
#define MatrixFX_h

#define MFX_MIN_BRIGHTNESS 0
#define MFX_MAX_BRIGHTNESS 15
#define MFX_DEFAULT_BRIGHTNESS 5
#define MFX_DEFAULT_WIDTH 8
#define MFX_DEFAULT_HEIGHT 8

/**
 * Enumeration of the effects.
 */
enum effect {
  rain,
  random_fill,
  pulse,
  scan_vertical,
  scan_horizontal,
  box_zoom
};

/**
 * MatrixFX effects library
 * http://code.google.com/p/matrix-fx/
 *
 * (c) Pete Baker 2010
 */
class MatrixFX {
public:
	MatrixFX(int dataPin, int clockPin, int loadPin);
	MatrixFX(int dataPin, int clockPin, int loadPin, int bufferWidth, int bufferHeight);
	void setBrightness(int brightness);
	void increaseBrightness();
	void decreaseBrightness();
	int getBufferSize();
	void clear();
	void initEffect(effect eff);
	void nextEffect();
	
	/**
	 * Updates the current effect.
	 */
	void update();
	
private:
	
	/**
	 * Pointer to the LED matrix.
	 */
	Matrix _matrix;
	
	/**
	 * Pointer to the LED frame buffer.
	 */
	Sprite _buffer;
	
	/**
	 * LED brightness: 0 to 15.
	 */
	int _brightness;
	
	/**
	 * The active effect.
	 */
	effect _activeEffect;
	
	/**
	 * Effect state structure.
	 */
	struct fx_state {
		int x;
		int y;
		int inc;
		int state;
		bool isHorizontal;
	}_fx;	
	
	/**
	 * Effect function typedef.
	 */
	typedef void (MatrixFX::*EffectUpdateFn)(void);
	
	/**
	 * Function pointer to the current effect update method.
	 */
	EffectUpdateFn _update;

	/**
	 * Class initialisation function.
	 */ 
	void _init();
	
	/**
	 * Effect initialisation methods.
	 */
	void effect_rain_init();
	void effect_random_fill_init();
	void effect_pulse_init();
	void effect_scan_vertical_init();
	void effect_scan_horizontal_init();
	void effect_box_zoom_init();
	
	/**
	 * Effect function prototypes.
	 */
	void effect_rain_update();
	void effect_random_fill_update();
	void effect_pulse_update();
	void effect_scan_vertical_update();
	void effect_scan_horizontal_update();
	void effect_scan_init(bool isHorizontal);
	void effect_scan_update();
	void effect_box_zoom_update();
	
	/**
	 * Utility methods.
	 */
	void emptyLine(int x);
	void printSpriteHorizontal(int xPos);
	void printSpriteVertical(int yPos);
	void fill(byte state);
};

#endif
